<?php
/**
 * Created by PhpStorm.
 * User: admin
 * Date: 2019-03-20
 * Time: 02:17
 */

namespace BeReborn\Route;


use BeReborn\Exception\RequestException;
use BeReborn\Web\Controller;
use Closure;

/**
 * Class Middleware
 * @package BeReborn\Route
 */
class Middleware
{

	/** @var array */
	private $middleWares = [];

	private $params = [];

	/**
	 * @param $call
	 * @return $this
	 */
	public function set($call)
	{
		$this->middleWares[] = $call;
		return $this;
	}

	/**
	 * @param array $array
	 * @return $this
	 */
	public function setMiddleWares(array $array)
	{
		$this->middleWares = $array;
		return $this;
	}

	/**
	 * @param $data
	 * @return $this
	 */
	public function bindParams($data)
	{
		$this->params = $data;
		return $this;
	}

	/**
	 * @param $controllerCallback
	 * @return mixed
	 */
	public function getGenerate($controllerCallback)
	{
		$last = function ($passable) use ($controllerCallback) {
			if ($controllerCallback instanceof \Closure) {
				return call_user_func($controllerCallback, $passable);
			}

			if (!is_array($controllerCallback)) {
				throw new \Exception('404 NOT FOUND.');
			}

			[$controller, $method] = $controllerCallback;
			if ($controller instanceof Controller) {
				$controller->setRequest(request());
				$controller->setInput(request()->params);
				$controller->setHeaders(request()->headers);
			}
			return call_user_func($controllerCallback, $passable);
		};
		$data = array_reduce(array_reverse($this->middleWares), $this->core(), $last);
		$this->middleWares = [];

		return $data;
	}

	/**
	 * @return Closure
	 */
	public function core()
	{
		return function ($stack, $pipe) {
			return function ($passable) use ($stack, $pipe) {
				if ($pipe instanceof IMiddleware) {
					return $pipe->handler($passable, $stack);
				} else {
					return $pipe($passable, $stack);
				}
			};
		};
	}

}
